package com.J.Plane;
import static android.opengl.GLES10.*;


import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLSurfaceView;
import android.opengl.GLU;

import java.util.Vector;

/**
 * The object represents plane on 3d world.
 *
 */
public class Plane extends Entity {
	
	private BitmapMaterial	mMaterial;
	
	private float mWidth;
	private float mHeight;
	
	private int mSegmentsW;
	private int mSegmentsH;
	
	private Vector<Triangle3D> mFaces = new Vector<Triangle3D>();
	private Vector<Vector3>	mVerticies = new Vector<Vector3>();

	
	/**
	 * Private constructor.
	 * This is only for internal usage.
	 */
	private Plane() {		
	}
	
	/**
	 * Construct plane
	 * @param width			Width of plane
	 * @param height		Height of plane
	 * @param segmentsW		Horizontal segments
	 * @param segmentsH		Vertical segments
	 */
	public Plane(float width, float height, int segmentsW, int segmentsH,
				 BitmapMaterial material) {
		this.mWidth = width;
		this.mHeight = height;
		this.mSegmentsW = segmentsW;
		this.mSegmentsH = segmentsH;
		this.mMaterial = material;
		
		buildPlane(width, height);
	}
	
	
	
	/**
	 * Build plane
	 * @param [in]w		Width
	 * @param [h]h		Height
	 */
	private void buildPlane(float w, float h) {
		int gridX = this.mSegmentsW;
		int gridY = this.mSegmentsH;
		
		int gridX1 = gridX +1;
		int gridY1 = gridY +1;
		
		float stepW = w/gridX;
		float stepH = -h/gridY;
		
		float textureX = w/2;
		float textureY = h/2;
		
		for(int ix =0; ix < gridX1; ix++){
			for(int iy =0; iy < gridY1; iy++){
				float x = ix * stepW - textureX;
				float y = iy * stepH + textureY;
				
				mVerticies.add(new Vector3(x,y,0));
			}
		}
		
		//		1----2  1st triangle ClockWise  |			3  2nd triangle ClockWise        
		//		|   /							|		  /	|
		//		|  /							|	    /	|
		//		| /								|	  /		|
		//		3								|	 2------1
		Vector3[] verticies = new Vector3[3];
		NumberUV[] uvs  = new NumberUV[] {
			new NumberUV(0, 0),
			new NumberUV(0, 0),
			new NumberUV(0, 0)
		};
		
		// 
		// TODO: More optimization is possible.
		// 
		for(int ix=0 ; ix < gridX; ix++){
			for(int iy=0 ;iy < gridY; iy++ ){
				// 1st triangle
				verticies[0] = mVerticies.get(ix		*gridY1		+ iy   );
				verticies[1] = mVerticies.get((ix+1)	*gridY1 	+ iy   );
				verticies[2] = mVerticies.get(ix		*gridY1 	+ iy +1);
				uvs[0].set(ix   /(float)gridX, 	iy / (float)gridY);
				uvs[1].set((ix+1)/(float)gridX,  	iy /(float)gridY);
                uvs[2].set(ix   /(float)gridX, 		(iy+1)/(float)gridY);
                
                //Log.v("TEST", "uv->" + uv[0] + "," + uv[1] + "," + uv[2]);
                
                mFaces.add(new Triangle3D(verticies,uvs));
                
				// 2nd triangle
                verticies[0] = mVerticies.get((ix+1)  * gridY1  + iy + 1  );
				verticies[1] = mVerticies.get(ix      * gridY1  + iy + 1  );
				verticies[2] = mVerticies.get((ix+1)  * gridY1  + iy	   );
				uvs[0].set((ix+1)/(float)gridX,  	(iy+1)/(float)gridY);
				uvs[1].set((ix/(float)gridX), 		(iy+1)/(float)gridY);
                uvs[2].set((ix+1)/(float)gridX,		iy/(float)gridY);
                
                //Log.v("TEST", "uv->" + uv[0] + "," + uv[1] + "," + uv[2]);
                
                mFaces.add(new Triangle3D(verticies,uvs));
			}
		}		
	}
	
	/**
	 * Clone plane instance
	 */
	public Entity clone() {
		Plane p = new Plane();
		
		p.mMaterial = this.mMaterial;
		p.mWidth = this.mWidth;
		p.mHeight = this.mHeight;
		p.mSegmentsH = this.mSegmentsH;
		p.mSegmentsW = this.mSegmentsW;
		
		p.mFaces = (Vector<Triangle3D>) this.mFaces.clone();
		p.mVerticies = (Vector<Vector3>) this.mVerticies.clone();
		
		return this;
	}
	
	/**
	 * Render plane
	 */
	public void render(GL10 gl){
		
		mMaterial.setupForRendering(gl);
		
		gl.glEnableClientState(GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		
		int len = mFaces.size();
		for(int i=0;i<len;++i) {
			mFaces.get(i).render();
		}
	}
}
